package com.onesports.intelligent.k12.polarlight.security;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.onesports.intelligent.k12.polarlight.domain.vo.auth.DataPermissionVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * Utility class for Spring Security.
 *
 * @author aj
 */
@Slf4j
public final class SecurityUtils {
    public static final String ANONYMOUS_USER = "anonymousUser";

    private SecurityUtils() {
    }

    /**
     * Get the login of the current user.
     *
     * @return the login of the current user.
     */
    public static Optional<String> getCurrentUserLogin() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        return Optional.ofNullable(extractPrincipal(securityContext.getAuthentication()));
    }

    private static String extractPrincipal(Authentication authentication) {
        if (authentication == null) {
            return null;
        } else if (authentication.getPrincipal() instanceof UserDetails) {
            UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
            return springSecurityUser.getUsername();
        } else if (authentication.getPrincipal() instanceof String) {
            return (String) authentication.getPrincipal();
        }
        return null;
    }

    public static Optional<DomainUserDetails> getCurrentUserDetails() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        Authentication authentication = securityContext.getAuthentication();
        DomainUserDetails userDetails = null;
        if (ObjectUtils.isNotEmpty(authentication)) {
            if (authentication.getDetails() instanceof UserDetails) {
                return Optional.of((DomainUserDetails) authentication.getDetails());
            } else if (!ANONYMOUS_USER.equals(authentication.getPrincipal())) {
                ObjectMapper mapper = new ObjectMapper();
                try {
                    String json = mapper.writeValueAsString(authentication.getPrincipal());
                    userDetails = mapper.readValue(json, DomainUserDetails.class);
                } catch (JsonProcessingException e) {
                    log.error("序列化/反序列化异常===", e);
                }
                return Optional.ofNullable(userDetails);
            }
        }
        return Optional.ofNullable(userDetails);
    }

    /**
     * Get the JWT of the current user.
     *
     * @return the JWT of the current user.
     */
    public static Optional<String> getCurrentUserJWT() {
        SecurityContext securityContext = SecurityContextHolder.getContext();
        return Optional
                .ofNullable(securityContext.getAuthentication())
                .filter(authentication -> authentication.getCredentials() instanceof String)
                .map(authentication -> (String) authentication.getCredentials());
    }

    /**
     * Check if a user is authenticated.
     *
     * @return true if the user is authenticated, false otherwise.
     */
    public static boolean isAuthenticated() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication != null && getAuthorities(authentication).noneMatch(AuthoritiesConstants.ANONYMOUS::equals);
    }

    /**
     * Checks if the current user has a specific authority.
     *
     * @param authority the authority to check.
     * @return true if the current user has the authority, false otherwise.
     */
    public static boolean hasCurrentUserThisAuthority(String authority) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        return authentication != null && getAuthorities(authentication).anyMatch(authority::equals);
    }

    private static Stream<String> getAuthorities(Authentication authentication) {
        return authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority);
    }

    /**
     * 获取姓名
     *
     * @return
     */
    public static String getNickname() {
        String nickname = "";
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            nickname = currentUserDetails.get().getNickname();
        }
        return nickname;
    }

    /**
     * 获取当前登录用户的organizationId
     *
     * @return String
     */
    public static String getOrganizationId() {
        String organizationId = null;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            organizationId = currentUserDetails.get().getOrganizationId();
        }
        return organizationId;
    }


    /**
     * 获取当前登录用户的organizationId
     *
     * @return String
     */
    public static List<String> getCampusIds() {
        List<String> campusIds = null;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            campusIds = currentUserDetails.get().getDataPermissionVO().getCampusIds();
        }
        return campusIds;
    }


    /**
     * 获取当前登录用户id
     * 微信登录时为wx_user,id
     *
     * @return String
     */
    public static String getAccountId() {
        String accountId = null;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            accountId = currentUserDetails.get().getCurrent();
        }
        return accountId;
    }


    /**
     * 获取当前登录是否超管
     *
     * @return String
     */
    public static boolean isSuper() {
        boolean isSuper = false;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            isSuper = currentUserDetails.get().isSuperAdmin();
        }
        return isSuper;
    }

    public static String getSystemCode() {
        String systemCode = null;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            systemCode = currentUserDetails.get().getSystemCode();
        }
        return systemCode;
    }


    /**
     * 获取当前登录用户职工id
     *
     * @return String
     */
    public static String getStaffId() {
        String staffId = null;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            staffId = currentUserDetails.get().getStaffId();
        }
        return staffId;
    }

    /**
     * 家长端获取手机号
     *
     * @return
     */
    public static String getPhone() {
        String phone = null;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            phone = currentUserDetails.get().getPhone();
        }
        return phone;
    }

    public static boolean isCoach() {
        boolean isCoach = false;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            isCoach = currentUserDetails.get().isCoach();
        }
        return isCoach;
    }

    public static String getCoachId() {
        String coachId = null;
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            coachId = currentUserDetails.get().getCoachId();
        }
        return coachId;
    }

    public static DataPermissionVO getDataPermission() {
        Optional<DomainUserDetails> currentUserDetails = getCurrentUserDetails();
        if (null != currentUserDetails && currentUserDetails.isPresent()) {
            return currentUserDetails.get().getDataPermissionVO();
        }
        return null;
    }
}
